<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>BlockValues</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'BlockValues' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">BasicInformKit</a></li><li><b>BlockValues</b></li></ul></div>
<p class="purpose">BlockValues  Routines for copying, comparing, creating and destroying block values, and for reading and writing them as if they were arrays.</p>

<ul class="toc"><li><a href="blckv.html#SP1">&#167;1. Overview</a></li><li><a href="blckv.html#SP2">&#167;2. Short Block Format</a></li><li><a href="blckv.html#SP3">&#167;3. Long Block Access</a></li><li><a href="blckv.html#SP4">&#167;4. Weak Kind</a></li><li><a href="blckv.html#SP5">&#167;5. Reference counting</a></li><li><a href="blckv.html#SP6">&#167;6. Changing Reference Counts</a></li><li><a href="blckv.html#SP7">&#167;7. Long Block Capacity</a></li><li><a href="blckv.html#SP8">&#167;8. Long Block Array Access</a></li><li><a href="blckv.html#SP9">&#167;9. First Zero Entry</a></li><li><a href="blckv.html#SP10">&#167;10. Mass Copy Entries</a></li><li><a href="blckv.html#SP11">&#167;11. Mass Copy From Array</a></li><li><a href="blckv.html#SP12">&#167;12. Creation</a></li><li><a href="blckv.html#SP13">&#167;13. Errors</a></li><li><a href="blckv.html#SP14">&#167;14. Short Block Allocation</a></li><li><a href="blckv.html#SP15">&#167;15. Long Block Allocation</a></li><li><a href="blckv.html#SP16">&#167;16. Block Values On Stack</a></li><li><a href="blckv.html#SP17">&#167;17. Freeing</a></li><li><a href="blckv.html#SP18">&#167;18. Quick Copy</a></li><li><a href="blckv.html#SP21">&#167;21. Slow Copy</a></li><li><a href="blckv.html#SP22">&#167;22. Copy</a></li><li><a href="blckv.html#SP23">&#167;23. Destruction</a></li><li><a href="blckv.html#SP24">&#167;24. Recycling</a></li><li><a href="blckv.html#SP25">&#167;25. Mutability</a></li><li><a href="blckv.html#SP26">&#167;26. Casting</a></li><li><a href="blckv.html#SP27">&#167;27. Comparison</a></li><li><a href="blckv.html#SP28">&#167;28. Debugging</a></li><li><a href="blckv.html#SP29">&#167;29. Printing Memory Addresses</a></li><li><a href="blckv.html#SP30">&#167;30. Hexadecimal Printing</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Overview.</b>Each I7 value is represented at run-time by an I6 word: on the Z-machine,
a 16-bit number, and on Glulx, a 32-bit number. The correspondence between
these numbers and the original values depends on the kind of value: "number"
comes out as a signed twos-complement number, but "time" as an integer
number of minutes since midnight, "rulebook" as the index of the rulebook
in order of creation, and so on.
</p>

<p class="commentary">Even if a 32-bit number is available, this is not enough to represent the
full range of values we might want: consider all the possible hundred-word
essays of text, for instance. So for a whole range of kinds &mdash; "text",
"list of K", "stored action" and so on &mdash; the I6 value at run-time is only
a pointer to what is called a "short block". This is typically only a few
words long, and often only a single word: hence the term "short". It has
no header or other overhead, and its contents depend on the kind of value.
</p>

<p class="commentary">If we know that a given kind of value can be stored in, say, exactly 128
bits, then it's possible simply to store the whole thing in the short block.
More often, though, the data needs to be flexible in size, or needs to
be large. In that case, the short block will include (and sometimes, will
consist only of) a pointer to data stored in a "long block". Unlike the
short block, the long block is a chunk of memory stored using the Flex
system, and thus is genuinely a "block" in the sense of the Flex
documentation.
</p>

<p class="commentary">It's possible to have several different short blocks each pointing to the
same long block of underlying data: for example, the result of the I7 code
</p>

<p class="commentary">	let L1 be { 2, 3, 5, 7, 11 };
	let L2 be L1;
</p>

<p class="commentary">is to create L1 and L2 as pointers to two different short blocks, but the
two SBs each point to the same long block, which contains the data for the
list 2, 3, 5, 7, 11. Note that this makes it very fast to copy L1's contents
into L2, because only L2's short block needs to change.
</p>

<p class="commentary">The rules for customers who want to deal with values like this are much like
the rules for allocating memory with Flex. Calling <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span>
creates a new value, but this must always, and only once, later be disposed
of using <span class="extract"><span class="extract-syntax">BlkValueFree</span></span>.
</p>

<p class="commentary">So if the short blocks of L1 and L2 both point to the same long block of
actual data, what happens when only one of them is freed? The answer is that
every long block has a reference count attached, which counts the number of
short blocks pointing to it. In our example, this count is 2. If list L1
is freed, the long block's reference count is decremented to 1, but it
remains in memory, and only L1's short block is given up; when list L2 is
subsequently freed, both its short block and the now unwanted long block
are given up.
</p>

<p class="commentary">The harder case to handle is what happens when L1 and L2 share a long
block containing 2, 3, 5, 7, 11, but when the source text asks to "add 13
to L1". If we simply changed the long block, that would affect L2 as well.
So we must first make L1 "mutable". This means copying the long block
to make a new unique copy with reference count 1; assigning that to L1
in place of the original; and decrementing the reference count of the
original from 2 to 1. L1 and L2 now point to two different long blocks,
so it's safe to modify L1's.
</p>

<p class="commentary">Subtle and beautiful bugs can occur as a result of making a value mutable
at the wrong moment. Beware in particular of reading data out of a long
block, then writing it back again, because the act of writing may force
the value owning the long block to become mutable; this will make a new
copy of the data; but you will be left holding the old copy. Since these
are functionally identical, you may not even notice, but calamities will
occur later because the version of the value you're holding really
belongs to somebody else and may be freed at any point.
</p>

<p class="commentary">Finally, note that the I7 compiler also creates block values representing
constants. For example, the source text
</p>

<p class="commentary">	let L1 be { 2, 3, 5, 7, 11 };
</p>

<p class="commentary">causes a block value representing this list to be stored in memory. The
long block for a constant needs to be immortal, since this memory must
never be freed: it's therefore given a reference count of "infinity".
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MAX_POSITIVE_NUMBER</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Short Block Format.</b>A short block begins with a word which is usually, but not always, a pointer
to the long block. There are three possibilities:
</p>

<ul class="items"><li>(a) 0 means the short block has length 1 and the long block begins at the
very next word in memory. This makes it more convenient for I7 to compile
BV constants, but isn't otherwise used.
</li><li>(b) 1 to 255 means the short block has length 2 or more. The value is expected
to be a bitmap in bits 4 to 8 together with a nonzero ID in bits 1 to 4.
If the <span class="extract"><span class="extract-syntax">BLK_BVBITMAP_LONGBLOCK</span></span> bit is set, a pointer to the long block
is stored in the second word of the short block.
</li><li>(c) Otherwise the short block has length 1 and contains only a pointer to
the long block.
</li></ul>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax">           = </span><span class="constant-syntax">$ff</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVUSERBITMAP</span><span class="plain-syntax">       = </span><span class="constant-syntax">$0f</span><span class="plain-syntax">;</span>

<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$10</span><span class="plain-syntax">; </span><span class="comment-syntax">Word 1 of SB is pointer to LB</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXT</span><span class="plain-syntax">      = </span><span class="constant-syntax">$20</span><span class="plain-syntax">; </span><span class="comment-syntax">BV holds a TEXT_TY value</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANT</span><span class="plain-syntax">  = </span><span class="constant-syntax">$40</span><span class="plain-syntax">; </span><span class="comment-syntax">BV holds a constant value</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_SBONLY</span><span class="plain-syntax">  = </span><span class="constant-syntax">$80</span><span class="plain-syntax">; </span><span class="comment-syntax">No LB, and kind ID is in word 1 of SB</span>

<span class="plain-syntax">#</span><span class="identifier-syntax">IFTRUE</span><span class="plain-syntax"> </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_USERBITMAPMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$fffffff0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCKMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ffffff10</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXTMASK</span><span class="plain-syntax">      = </span><span class="constant-syntax">$ffffff20</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANTMASK</span><span class="plain-syntax">  = </span><span class="constant-syntax">$ffffff40</span><span class="plain-syntax">;</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">IFNOT</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_USERBITMAPMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$fff0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCKMASK</span><span class="plain-syntax"> = </span><span class="constant-syntax">$ff10</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_TEXTMASK</span><span class="plain-syntax">      = </span><span class="constant-syntax">$ff20</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">BLK_BVBITMAP_CONSTANTMASK</span><span class="plain-syntax">  = </span><span class="constant-syntax">$ff40</span><span class="plain-syntax">;</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">ENDIF</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Long Block Access.</b>Illustrating this:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax"> == </span><span class="identifier-syntax">o</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_LONGBLOCK</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;1;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. Weak Kind.</b>This returns the weak kind ID of a block value. Most of the time this
information is stored in the long block, but that poses a problem for BVs
which have no long block: we must use the bitmap instead.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;(</span><span class="identifier-syntax">BLK_HEADER_KOV</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_BVBITMAP</span><span class="plain-syntax"> == </span><span class="identifier-syntax">o</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_TEXT</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TEXT_TY</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_SBONLY</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">KindWeakID</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;1);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;1;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_KOV</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NIL_TY</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Reference counting.</b>Reference counts lie in a word at a fixed offset from the start of the
long block: doctrinally, any block value with no long block at all (such
as a piece of packed text) has reference count infinity.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Changing Reference Counts.</b>When incrementing, infinity's the limit; when decrementing, it never
reduces. Note that the decrement function returns the new reference count,
but the increment function returns nothing. It's only when reference counts
go downwards that we have to worry about whether something happens.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax"> = </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">refc</span><span class="plain-syntax">--;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"reference count negative"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_HEADER_RCOUNT</span><span class="plain-syntax"> = </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;0) &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_SBONLY</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Long Block Capacity.</b>As we've seen, the long block has some metadata in a header, but otherwise
it's organised as if it were an array, with byte or word-sized entries.
At any given time, the "capacity" of the LB is the number of entries in
this array: that doesn't mean that the BV is using them all at any given moment.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueLBCapacity</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">  </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexTotalSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax"> / </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">array_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">  </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">FlexResize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">FlexResize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">new_capacity</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. Long Block Array Access.</b>Though the customer thinks he's getting an array, in fact the storage in
the LB is not necessarily contiguous, since it can span multiple Flex blocks.
We abstract that with two routines to read and write entries.
</p>

<p class="commentary"><span class="extract"><span class="extract-syntax">BlkValueRead</span></span> takes two compulsory arguments and one optional one. Thus:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">reads the nth entry in the long block for <span class="extract"><span class="extract-syntax">bv</span></span>, whereas
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="reserved-syntax">true</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">read it from the given long block directly. <span class="extract"><span class="extract-syntax">BlkValueWrite</span></span> is similar.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueReadLB</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueReadSB</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueReadLB</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;0;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueRead: reading from index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueReadSB</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;0;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueRead: reading from index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWrite</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">do_not_indirect</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueWriteLB</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueWriteSB</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWriteSB</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="reserved-syntax">to</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueWrite: writing to index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueWriteLB</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">entry_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="reserved-syntax">to</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">:</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> + </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;0 = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">seek_byte_position</span><span class="plain-syntax"> - </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print_ret</span><span class="plain-syntax"> </span><span class="string-syntax">"*** BlkValueWriteLB: writing to index out of range: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">" in "</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="string-syntax">" ***"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. First Zero Entry.</b>This returns the entry index of the first zero entry in the long block's array,
or -1 if it has no zeros.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSeekZeroEntry</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">~=</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">: </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">=</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">=</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">--&gt;0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">)/</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">: </span><span class="identifier-syntax">addr</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">addr</span><span class="plain-syntax">-&gt;0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">byte_position</span><span class="plain-syntax"> + </span><span class="identifier-syntax">chunk_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Mass Copy Entries.</b>This copies a given number of entries from one BV's long block to another;
they must both be of the same word size but can differ in header size.
Functionally, it's identical to
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">n</span><span class="plain-syntax">=0: </span><span class="identifier-syntax">n</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">: </span><span class="identifier-syntax">n</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueWrite</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="identifier-syntax">BlkValueRead</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">));</span>
</pre>
<p class="commentary">but it's much, much faster, and runs in a reasonably small number of cycles
given what it needs to do.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueMassCopyEntries</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_header_size_in_bytes</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size_in_bytes</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; (</span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax"> + </span><span class="identifier-syntax">BLK_FLAG_TRUNCMULT</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy resizing failed"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="reserved-syntax">true</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy destination exhausted"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">from_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy source exhausted"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size_in_bytes</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">min</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">min</span><span class="plain-syntax">) </span><span class="identifier-syntax">min</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">min</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">Memcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Memcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">min</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bytes_to_copy</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bytes_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> + </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_bytes_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">min</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Mass Copy From Array.</b>The following is helpful when reading an array of characters into a text:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueMassCopyFromArray</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_entry_size</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">flags</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_FLAGS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; (</span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax"> + </span><span class="identifier-syntax">BLK_FLAG_TRUNCMULT</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">BlkValueSetLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy resizing failed"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flags</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_MULTI_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">)/</span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Arrcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_array</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> - </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_array</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax">*</span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">BLK_NEXT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy source exhausted"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">to_addr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax"> + </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">to_entries_left</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FlexSize</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_long_block</span><span class="plain-syntax">) - </span><span class="identifier-syntax">to_header_size</span><span class="plain-syntax">)/</span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Arrcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_addr</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_array</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_entry_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. Creation.</b>To create a block value, call:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">where <span class="extract"><span class="extract-syntax">K</span></span> is its (strong) kind ID. Optionally, call:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">to mandate that the short block needs to be located at the given address
outside the heap: but don't do this unless you can guarantee that space of the
necessary length will be available there for as long as the lifetime of
the value; and please note, it really does matter that this address lies
outside the heap, for reasons to be seen below.
</p>

<p class="commentary">These work by delegating to the kind's creator function, which returns the
address of the short block for the new value.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax"> </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">  </span><span class="identifier-syntax">creator</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">creator</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">CREATE_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">short_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">creator</span><span class="plain-syntax">(</span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LKTRACE_HEAP</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Created: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="comment-syntax">The new value is represented in I6 as the pointer to its short block:</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">short_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. Errors.</b>No I7 source text should ever result in a call to this, unless it does
unpleasant things at the I6 level.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax"> </span><span class="identifier-syntax">reason</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">IssueRTP</span><span class="plain-syntax">(</span><span class="string-syntax">"MemoryAllocationFailed"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"Memory allocation proved impossible."</span><span class="plain-syntax">, </span><span class="identifier-syntax">BasicInformKitRTPs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"*** Value handling failed: "</span><span class="plain-syntax">, (</span><span class="reserved-syntax">string</span><span class="plain-syntax">) </span><span class="identifier-syntax">reason</span><span class="plain-syntax">, </span><span class="string-syntax">" ***^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    @</span><span class="reserved-syntax">quit</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. Short Block Allocation.</b>As can be seen, if the <span class="extract"><span class="extract-syntax">sb_address</span></span> is zero then we need to conjure up memory
from somewhere: we do this using Flex. That incurs a fair amount of overhead in
time and memory, though. The SB data is stored in the data portion of the Flex
block, which is why we get its address from by adding the data offset to the
block address.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateSB</span><span class="plain-syntax"> </span><span class="identifier-syntax">sb_address</span><span class="plain-syntax"> </span><span class="identifier-syntax">size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sb_address</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">sb_address</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FlexAllocate</span><span class="plain-syntax">(</span><span class="identifier-syntax">size</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">) + </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sb_address</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. Long Block Allocation.</b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateLB</span><span class="plain-syntax"> </span><span class="identifier-syntax">extent</span><span class="plain-syntax"> </span><span class="identifier-syntax">weak_id</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FlexAllocate</span><span class="plain-syntax">(</span><span class="identifier-syntax">extent</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">, </span><span class="identifier-syntax">weak_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateMultipleLB</span><span class="plain-syntax"> </span><span class="identifier-syntax">extent</span><span class="plain-syntax"> </span><span class="identifier-syntax">weak_id</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FlexAllocate</span><span class="plain-syntax">(</span><span class="identifier-syntax">extent</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">, </span><span class="identifier-syntax">weak_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">BLK_FLAG_MULTIPLE</span><span class="plain-syntax"> + </span><span class="identifier-syntax">BLK_FLAG_WORD</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. Block Values On Stack.</b>As noted above, it's wasteful to keep allocating short blocks using Flex.
For the short blocks of block values in local variables, we store them on
a stack instead. This is a top-down stack, so the current stack frame
starts out just after the end of the stack area in memory (and therefore
points to an empty stack frame); it drops down as new frames are created.
</p>

<p class="commentary"><span class="extract"><span class="extract-syntax">BlkValueCreateOnStack</span></span> acts exactly like <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span>, but stores
the short block at the given word offset in the current stack frame.
(I7 compiles calls to these routines when compiling code to manage
local variables.)
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">StackFramingInitialise</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> = </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">BLOCKV_STACK_SIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">StackFrameCreate</span><span class="plain-syntax"> </span><span class="identifier-syntax">size</span><span class="plain-syntax"> </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">new</span><span class="plain-syntax"> = </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> - </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">new</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">IssueRTP</span><span class="plain-syntax">(</span><span class="string-syntax">"MemoryAllocationFailed"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="string-syntax">"Memory allocation proved impossible."</span><span class="plain-syntax">, </span><span class="identifier-syntax">BasicInformKitRTPs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"*** Stack frame of "</span><span class="plain-syntax">, </span><span class="identifier-syntax">size</span><span class="plain-syntax">, </span><span class="string-syntax">" could not be created ***^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        @</span><span class="reserved-syntax">quit</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCreateOnStack</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset</span><span class="plain-syntax"> </span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">strong_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">offset</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueFreeOnStack</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">offset</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. Freeing.</b>As noted above, every value returned by <span class="extract"><span class="extract-syntax">BlkValueCreate</span></span> must later be
freed by calling the following routine exactly once:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">In particular, if a block value is stored in any I6 location which is about
to be overwritten with a new value, it's essential to call this in order
properly to dispose of the old value.
</p>

<p class="commentary">As noted above, short blocks are sometimes created within Flex blocks on
the heap, using <span class="extract"><span class="extract-syntax">FlexAllocate</span></span>; and if this is one of those, we need to free
the relevant Flex block.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueFree</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="comment-syntax">Free any heap memory occupied by the short block</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> - </span><span class="identifier-syntax">Flex_Heap</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">MEMORY_HEAP_SIZE</span><span class="plain-syntax"> + </span><span class="constant-syntax">16</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">FlexFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> - </span><span class="identifier-syntax">BLK_DATA_OFFSET</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. Quick Copy.</b>The basic method of copying block value B into block value A is to destroy the
old contents of A, which are about to be overwritten; then copy the short
block of A into the short block of B, a quick process; and increment the
reference count of B.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueQuickCopyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueCopyShortBlocks</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP19" class="paragraph-anchor"></a><b>&#167;19. </b>Short blocks can mostly be copied automatically, but we provide a hook
for kinds to intervene.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopyShortBlocks</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> </span><span class="identifier-syntax">sbc_function</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">sbc_function</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">COPY_SHORT_BLOCK_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sbc_function</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">sbc_function</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">SHORT_BLOCK_SIZE_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueCopySB</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP20" class="paragraph-anchor"></a><b>&#167;20. </b>The surprising line in this function is the last one, to deal with the
convention that a pointer value of 0 means the LB immediately follows the SB: if
that's true in <span class="extract"><span class="extract-syntax">from_bv</span></span>, it won't be true in <span class="extract"><span class="extract-syntax">to_bv</span></span>, so we must correct it.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopySB</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">size</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">size</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="constant-syntax">1</span><span class="plain-syntax">:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="constant-syntax">2</span><span class="plain-syntax">:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;0 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">--&gt;0;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;1 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">--&gt;1;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;1 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;1 = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> + </span><span class="constant-syntax">2</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">default</span><span class="plain-syntax">:</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0: </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">size</span><span class="plain-syntax">: </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">size</span><span class="plain-syntax">-1;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">i</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> + </span><span class="identifier-syntax">size</span><span class="plain-syntax">*</span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP21" class="paragraph-anchor"></a><b>&#167;21. Slow Copy.</b>Why don't we always do this? Consider the case where B is a list of rooms, and
A is a list of objects. If we give A's short block a pointer to the long block
of B, A will suddenly change its kind as well as its contents, because the
strong kind of a list is stored inside the long block. So there are a few
cases where it's not safe to make a quick copy. In any case, sooner or later
you have to duplicate actual data, not just rearrange pointers to it, and
here's where.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">recycling</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">copy_fn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">copy_fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">COPY_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">copy_fn</span><span class="plain-syntax">) </span><span class="identifier-syntax">copy_fn</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">recycling</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopyRawLongBlock</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">recycling</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> </span><span class="identifier-syntax">extent_fn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_long_block</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">recycling</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueRecyclePrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">extent_fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">LONG_BLOCK_SIZE_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">extent_fn</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">Routine</span><span class="plain-syntax">) </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">extent_fn</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">extent_fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> &lt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueLBCapacity</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueMassCopyEntries</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_entries_to_copy</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP22" class="paragraph-anchor"></a><b>&#167;22. Copy.</b>As noted above, some copies are quick, and some are slow. If the kind provides
a quick-copy function, we call to ask its permission to make a quick copy:
otherwise we go ahead and make one.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCopy</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">  </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">quick_copy_fn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy to null value"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy from null value"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> == </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LKTRACE_HEAP</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Copy: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="string-syntax">" to equal "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">from_kind</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"copy incompatible kinds"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">quick_copy_fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">QUICK_COPY_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">quick_copy_fn</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">quick_copy_fn</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="reserved-syntax">true</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">--&gt;0 &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_SBONLY</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">, </span><span class="reserved-syntax">true</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">else</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueQuickCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">from_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP23" class="paragraph-anchor"></a><b>&#167;23. Destruction.</b>We will also need primitives for two different forms of destruction. This
is something which should happen whenever a block value is thrown away,
not to be used again: either because it's being freed, or because new
contents are being copied into it.
</p>

<p class="commentary">The idea of destruction is that any data stored in the long block should
safely be disposed of. If the reference count of the long block is 2 or
more, there's no problem, because we can simply decrement the count and
let other people worry about the data from now on. But if it's only 1,
then destroying the data is on us. Since we don't know what's in the
long block, we have to ask the kind's destroy function to do it for us.
</p>

<p class="commentary">Note that all of this frequently causes recursion: destruction leads to
freeing of some of the data, which in turn means that that data must be
destroyed, and so on. So it's essential that block values be well-founded:
a list must not, for example, contain itself.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDestroyPrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">destructor</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LKTRACE_HEAP</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Destroying "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">destructor</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">), </span><span class="identifier-syntax">DESTROY_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">destructor</span><span class="plain-syntax">) </span><span class="identifier-syntax">destructor</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) </span><span class="identifier-syntax">FlexFree</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP24" class="paragraph-anchor"></a><b>&#167;24. Recycling.</b>This is like destruction in that it disposes of the value safely, but it
tries to keep the long block for reuse, rather than deallocating it. This
won't work if other people are still using it, so in the case where its
reference count is 2 or more, we simply reduce the count by 1 and then
replace the small block with a new one (at the same address).
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueRecyclePrimitive</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">destructor</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LKTRACE_HEAP</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Recycling "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">destructor</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">DESTROY_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">destructor</span><span class="plain-syntax">) </span><span class="identifier-syntax">destructor</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueIncRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">), </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP25" class="paragraph-anchor"></a><b>&#167;25. Mutability.</b>A block value is by definition mutable if it has a long block with reference
count 1, because then the data in the long block can freely be changed without
corrupting other block values.
</p>

<p class="commentary">If provided, a make-mutable function should either act on its own behalf and
return <span class="extract"><span class="extract-syntax">false</span></span>, or ask us to proceed by returning <span class="extract"><span class="extract-syntax">true</span></span>.
</p>

<p class="commentary">The way we do this is to create a temporary value to make a safe copy into; it
would be unnecessarily slow to allocate the short block for this safe copy on
the heap and then free it again moments later, so instead we put the short block
on the stack, making a temporary one-value stack frame instead to hold it.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkMakeMutable</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">block</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">make_mutable_function</span><span class="plain-syntax"> </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to make null block mutable"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LKTRACE_HEAP</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Make mutable: "</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">; #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>

<span class="plain-syntax">        </span><span class="identifier-syntax">BlkValueDecRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">        </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">make_mutable_function</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">MAKE_MUTABLE_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">make_mutable_function</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">make_mutable_function</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="reserved-syntax">false</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">SHORT_BLOCK_SIZE_KMF</span><span class="plain-syntax">);</span>

<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sb_size</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            @</span><span class="identifier-syntax">push</span><span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StackFrameCreate</span><span class="plain-syntax">(</span><span class="identifier-syntax">sb_size</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">BlkValueCreateOnStack</span><span class="plain-syntax">(0, </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">BlkValueSlowCopyPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">, </span><span class="reserved-syntax">false</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">BlkValueCopyShortBlocks</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            @</span><span class="identifier-syntax">pull</span><span class="plain-syntax"> </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP26" class="paragraph-anchor"></a><b>&#167;26. Casting.</b>We can also perform an assignment to an already-created block value in the
form of a cast, that is, a conversion of data from one kind to another:
or at least, for some kinds of value we can.
</p>

<p class="commentary">The cast function casts from the given value, with the given kind, into the
existing block value <span class="extract"><span class="extract-syntax">to_bv</span></span>. Note that the source value doesn't need to be a BV
itself. This mechanism is used, for example, to cast snippets to text.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCast</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">original_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">original_value</span><span class="plain-syntax">  </span><span class="identifier-syntax">cast_function</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cast_function</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ReadKindMetadata</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">), </span><span class="identifier-syntax">CAST_FN_KMF</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cast_function</span><span class="plain-syntax">) </span><span class="identifier-syntax">cast_function</span><span class="plain-syntax">(</span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_kind</span><span class="plain-syntax">, </span><span class="identifier-syntax">original_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">to_bv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP27" class="paragraph-anchor"></a><b>&#167;27. Comparison.</b>This looks at the data in the two BVs and returns 0 if they are equal, a positive
number if <span class="extract"><span class="extract-syntax">bv_right</span></span> is "greater than" <span class="extract"><span class="extract-syntax">bv_left</span></span>, and a negative number if
not. The interpretation of "greater than" depends on the kind, but should be
something which the user would find natural.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueCompare</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">  </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax"> </span><span class="identifier-syntax">cmp_fn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> == </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv_right</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_left</span><span class="plain-syntax"> - </span><span class="identifier-syntax">kind_right</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">cmp_fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">KindComparisonFunction</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind_left</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cmp_fn</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">BlkValueError</span><span class="plain-syntax">(</span><span class="string-syntax">"impossible comparison"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">cmp_fn</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv_left</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv_right</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP28" class="paragraph-anchor"></a><b>&#167;28. Debugging.</b>Surprisingly, the above system of reference-counted double indirection didn't
work first time, so it turned out to be useful to have these routines on hand.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkValueDebug</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax"> </span><span class="identifier-syntax">flag</span><span class="plain-syntax"> </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"(BV"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="identifier-syntax">flag</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">long_block</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetLongBlock</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;0 == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"..."</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"--&gt;"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"L"</span><span class="plain-syntax">; </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax">(</span><span class="identifier-syntax">long_block</span><span class="plain-syntax">, </span><span class="identifier-syntax">flag</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" 2**"</span><span class="plain-syntax">, </span><span class="identifier-syntax">long_block</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">BLK_HEADER_N</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">refc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">BlkValueGetRefCountPrimitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> == </span><span class="identifier-syntax">RC_INFINITY</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" resident"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span><span class="plain-syntax"> { </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" "</span><span class="plain-syntax">, </span><span class="identifier-syntax">refc</span><span class="plain-syntax">, </span><span class="string-syntax">" ref"</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">refc</span><span class="plain-syntax"> ~= </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"s"</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bv</span><span class="plain-syntax">--&gt;0) &amp; </span><span class="identifier-syntax">BLK_BVBITMAP_SBONLY</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"SBO"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">" = "</span><span class="plain-syntax">; </span><span class="identifier-syntax">SayKindValuePair</span><span class="plain-syntax">(</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">), </span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkValueWeakKind</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">) == </span><span class="identifier-syntax">TEXT_TY</span><span class="plain-syntax">) </span><span class="identifier-syntax">TEXT_TY_Debug</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">")"</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP29" class="paragraph-anchor"></a><b>&#167;29. Printing Memory Addresses.</b>The point of the anonymity flag is that, with this set, the output can be
used as the required output in an Inform test case without tiny movements
in memory between builds invalidating this required output.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkDebugAddress</span><span class="plain-syntax"> </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> </span><span class="identifier-syntax">flag</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">flag</span><span class="plain-syntax">) { </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"###"</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">blockv_stack</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax">*</span><span class="identifier-syntax">BLOCKV_STACK_SIZE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"s+"</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">I7SFRAME</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"=f"</span><span class="plain-syntax">; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"+"</span><span class="plain-syntax">; </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><span class="identifier-syntax">addr</span><span class="plain-syntax"> - </span><span class="identifier-syntax">Flex_Heap</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">d</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">MEMORY_HEAP_SIZE</span><span class="plain-syntax"> + </span><span class="constant-syntax">16</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"h+"</span><span class="plain-syntax">, (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">d</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">print</span><span class="plain-syntax"> (</span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax">) </span><span class="identifier-syntax">addr</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP30" class="paragraph-anchor"></a><b>&#167;30. Hexadecimal Printing.</b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkPrintHexadecimal</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">iftrue</span><span class="plain-syntax"> </span><span class="identifier-syntax">WORDSIZE</span><span class="plain-syntax"> == </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">$ffff0000</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">$ff000000</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10000000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$1000000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$100000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$1000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$100</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax"> / </span><span class="constant-syntax">$10</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>

<span class="plain-syntax">[ </span><span class="identifier-syntax">BlkPrintHexDigit</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">$F</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">10</span><span class="plain-syntax">) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> (</span><span class="identifier-syntax">char</span><span class="plain-syntax">) </span><span class="character-syntax">'A'</span><span class="plain-syntax"> + </span><span class="identifier-syntax">v</span><span class="plain-syntax"> - </span><span class="constant-syntax">10</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="flx.html">&#10094;</a></li><li class="progresssection"><a href="dfntn.html">dfntn</a></li><li class="progresssection"><a href="strtp.html">strtp</a></li><li class="progresssection"><a href="utlts.html">utlts</a></li><li class="progresssection"><a href="prgrp.html">prgrp</a></li><li class="progresssection"><a href="mthmt.html">mthmt</a></li><li class="progresssection"><a href="srt.html">srt</a></li><li class="progresssection"><a href="tbls.html">tbls</a></li><li class="progresssection"><a href="mstck.html">mstck</a></li><li class="progresssection"><a href="rlbks.html">rlbks</a></li><li class="progresssection"><a href="actvt.html">actvt</a></li><li class="progresssection"><a href="prntn.html">prntn</a></li><li class="progresssection"><a href="flx.html">flx</a></li><li class="progresscurrent">blckv</li><li class="progresssection"><a href="knds.html">knds</a></li><li class="progresssection"><a href="txt.html">txt</a></li><li class="progresssection"><a href="chr.html">chr</a></li><li class="progresssection"><a href="rgxp.html">rgxp</a></li><li class="progresssection"><a href="lsts.html">lsts</a></li><li class="progresssection"><a href="cmbnt.html">cmbnt</a></li><li class="progresssection"><a href="rltnk.html">rltnk</a></li><li class="progresssection"><a href="rltns.html">rltns</a></li><li class="progresssection"><a href="prprt.html">prprt</a></li><li class="progresssection"><a href="rtp.html">rtp</a></li><li class="progressnext"><a href="knds.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

